package com.ws;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.ResultUtils;
import com.constant.UserConstant;
import com.domain.dto.ChatDto;
import com.domain.dto.UserShowInfo;
import com.domain.entity.ChatMessage;
import com.domain.entity.User;
import com.exception.BusinessException;
import com.service.ChatMessageService;
import com.service.TeamService;
import com.service.UsersService;
import com.ws.message.MessageFormat;
import com.ws.strategy.MessageHandlerFactory;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.common.ErrorCode.FORBIDDEN;
import static com.constant.ChatType.PRIVATE;

/**
 * @author Administrator
 */
@ServerEndpoint("/chat/{userId}")
@Slf4j
@Component
public class WebSocket {
    private static SessionManager sessionManager;
    private static UsersService userService;
    private static MessageHandlerFactory messageHandlerFactory;

    @Autowired
    public WebSocket(UsersService userService,
                     SessionManager sessionManager,
                     MessageHandlerFactory messageHandlerFactory) {
        WebSocket.userService = userService;
        WebSocket.sessionManager = sessionManager;
        WebSocket.messageHandlerFactory = messageHandlerFactory;
    }

    public WebSocket() {
    }
    private Long senderId;
    private Session session;

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) throws IOException {
        try {
            this.senderId = userId;
            this.session = session;
            log.info("WebSocket连接,userId:{}", userId);
            User user = userService.getOne(new QueryWrapper<User>().eq("id", senderId));
            if (user.getUserStatus().equals(UserConstant.LOGOUT)) {
                throw new BusinessException(FORBIDDEN, "用户已下线，请重新登录!");
            }
            if (sessionManager.isConnection(userId)) {
                throw new BusinessException(FORBIDDEN, "已连接，不能重复开启会话!");
            }
            sessionManager.joinSession(userId, session);
        } catch (BusinessException e) {
            log.error(e.getDescription());
            session.getBasicRemote().sendText(JSONUtil.toJsonStr(ResultUtils.error(FORBIDDEN, e.getDescription())));
            session.close();
        }
        //开启同步
        WebSocketSync.startSync(session);
    }

    //TODO 需要处理并发访问占用同一个session问题
    @OnMessage
    public void onMessage(String mes, Session sendersession) {
        MessageFormat messageFormat = JSONUtil.toBean(mes, MessageFormat.class);
        Integer mesType = messageFormat.getType();
        messageHandlerFactory.process(mesType, mes);
    }

    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
        System.err.println("发生未知错误: " + throwable.getMessage());
    }

    @OnClose
    public void onClose() throws IOException {
        if (session != null) {
            session.close();
        }
        sessionManager.leaveSession(senderId);
    }
}
